home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / platforms and tools / mathlib / long doubles / long_double.c < prev   
Encoding:
C/C++ Source or Header  |  2000-09-28  |  5.6 KB  |  154 lines

  1. /*
  2.     File:        long_double.c
  3.  
  4.     Contains:    Routine demonstrating how to call MathLib functions that use 128 bit
  5.                 long doubles as arguments and return values.
  6.                 
  7.                 This is for PowerPC only, and the assembly code at the end is PowerPC
  8.                 assembly.  The MathLib library is a PowerPC only library.
  9.  
  10.                 This code has been tested with Metrowerks Codewarrior 10 and produces
  11.                 the same result as standard code compiled with Mr. C (with the 128 bit
  12.                 long double option turned on).
  13.  
  14.                 This code is needed to call the MathLib functions because the current
  15.                 Metrowerks compilers do not create a 128 bit long double, they create
  16.                 a 64 bit long double.  All of the MathLib functions that require a long
  17.                 double expect a 128 bit long double and therefore do not produce the
  18.                 correct results when given a 64 bit long double.
  19.  
  20.                 The callMathLib1ArgFcn routine takes three pointers, two pointers to
  21.                 long_doubles and one ProcPtr.  The first pointer to a long_double is
  22.                 the argument, the second pointer to a long_double is the result, and
  23.                 the ProcPtr is the MathLib function to be called.
  24.  
  25.                 The callMathLib2ArgFcn routine takes four pointers, three pointers to
  26.                 long_doubles and one ProcPtr.  The first two pointers to long_double's
  27.                 are the first two arguments to the function to be called, the third pointer
  28.                 to a long_double is the result returned by the function to be called, and
  29.                 the ProcPtr is the MathLib function to be called (in this example the powl
  30.                 function).
  31.  
  32.                 The callMathLibXArgFcn functions set up the floating point registers,
  33.                 call the MathLib function, and then return the results in the result
  34.                 structure.
  35.  
  36.                 The callMathLibFcn can easily be modified to deal with other functions
  37.                 which don't take only long doubles or return something other than a
  38.                 long double, but that is left up to the reader.
  39.  
  40.                 There are only 5 out of 46 functions in fp.h that these two routines
  41.                 don't cover.
  42.                 
  43.     Written by: Mark Cookson    
  44.  
  45.     Copyright:    Copyright © 1996-1999 by Apple Computer, Inc., All Rights Reserved.
  46.  
  47.                 You may incorporate this Apple sample source code into your program(s) without
  48.                 restriction. This Apple sample source code has been provided "AS IS" and the
  49.                 responsibility for its operation is yours. You are not permitted to redistribute
  50.                 this Apple sample source code as "Apple sample source code" after having made
  51.                 changes. If you're going to re-distribute the source, we require that you make
  52.                 it clear in the source that the code was descended from Apple sample source
  53.                 code, but that you've made changes.
  54.  
  55.     Change History (most recent first):
  56.                 8/18/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  57.                 
  58.  
  59. */
  60.  
  61. #include <stdio.h>
  62. #include <fp.h>
  63.  
  64. //what a real long double (double-double) looks like
  65. typedef struct long_double {
  66.     double    head;
  67.     double    tail;
  68. } long_double;
  69.  
  70. //prototype for functions which will call the passed MathLib function the correct way
  71. //this function can work for any function that takes one long double and returns a long double
  72. asm void callMathLib1ArgFcn ( ProcPtr fcn, long_double *x, long_double *res );
  73.  
  74. //this function can work for any function that takes two long doubles and returns a long double
  75. asm void callMathLib2ArgFcn ( ProcPtr fcn, long_double *x, long_double *y, long_double *res );
  76.  
  77. void main (void) {
  78.     long_double    x,
  79.                 y,
  80.                 ldResult;
  81.     double        dResult;
  82.  
  83.     x.head = 3.141592653;
  84.     x.tail = 0.0;
  85.     y.head = 5.0;
  86.     y.tail = 0.0;
  87.     ldResult.head = 0.0;
  88.     ldResult.tail = 0.0;
  89.  
  90.     callMathLib2ArgFcn ((ProcPtr)powl, &x, &y, &ldResult);
  91.  
  92.     //this is the correct conversion from a long double to a double
  93.     //See page 5-7 of Inside Macintosh:PowerPC Numerics
  94.     dResult = ldResult.head + ldResult.tail;
  95.  
  96.     printf ("The head is: %1.17e\nThe tail is: %1.17e\n", ldResult.head, ldResult.tail);
  97.     printf ("The value of ldResult converted to a double is: %1.17e\n", dResult);
  98. }
  99.  
  100. //This is PowerPC assembly for calling the PowerPC-only MathLib library.
  101. //These functions do the dirty work of setting things up for the call to the MathLib function.
  102. //This code is for ease of reading, not for speed.
  103. asm void callMathLib1ArgFcn ( ProcPtr fcn, long_double *x, long_double *res ) {
  104.         fralloc                    //create a stack frame because we will be calling other functions
  105.  
  106.         lwz        r8,x            //put pointer to argument into register
  107.  
  108.         lfd        fp1,0(r8)        //put the real arguments in the fp registers
  109.         lfd        fp2,8(r8)
  110.  
  111.         lwz        r12,fcn            //put the address of the function to call in r12
  112.         stw        RTOC,20(SP)        //setup the stack for the call
  113.         lwz        r0,0(r12)
  114.         lwz        RTOC,4(r12)
  115.         mtctr    r0
  116.         bctrl                    //call the MathLib function
  117.         lwz        RTOC,20(SP)        //restore our RTOC
  118.  
  119.         lwz        r10,res            //return our results in the res structure
  120.         stfd    fp1,0(r10)        //this is the head of the result
  121.         stfd    fp2,8(r10)        //this is the tail of the result
  122.  
  123.         frfree                    //clean up stack frame
  124.         blr                        //back from whence we came
  125. }
  126.  
  127. asm void callMathLib2ArgFcn ( ProcPtr fcn, long_double *x, long_double *y, long_double *res ) {
  128.         fralloc                    //create a stack frame because we will be calling other functions
  129.  
  130.         lwz        r8,x            //put pointers to arguments into registers
  131.         lwz        r9,y
  132.  
  133.         lfd        fp1,0(r8)        //put the real arguments in the fp registers
  134.         lfd        fp2,8(r8)
  135.         lfd        fp3,0(r9)
  136.         lfd        fp4,8(r9)
  137.  
  138.         lwz        r12,fcn            //put the address of the function to call in r12
  139.         stw        RTOC,20(SP)        //setup the stack for the call
  140.         lwz        r0,0(r12)
  141.         lwz        RTOC,4(r12)
  142.         mtctr    r0
  143.         bctrl                    //call the MathLib function
  144.         lwz        RTOC,20(SP)        //restore our RTOC
  145.  
  146.         lwz        r10,res            //return our results in the res structure
  147.         stfd    fp1,0(r10)        //this is the head of the result
  148.         stfd    fp2,8(r10)        //this is the tail of the result
  149.  
  150.         frfree                    //clean up stack frame
  151.         blr                        //back from whence we came
  152. }
  153.  
  154.